package com.hursing.tractor.model;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;

import com.hursing.tractor.controller.PlayController;

final class Strategy2 extends Strategy {

	/**
	 * 如果<=8张，>=4张 如果<=16张，>= 2/9
	 */
	@Override
	public void judgeWhetherFlip(Player player) {
		int cardCount = player.handyCardCount();
		if (cardCount < 8) {
			return;
		}
		// 统计权重值
		// int[] weight = new int[Card.COUNT_OF_SUIT_TYPE];
		for (int i = 0; i <= Card.SUIT_COUNT_WITHOUT_JOKER; i++) {
			if (!player.flipAbility(i)) {
				continue;
			}
			List<Card> cards = player.getCardsInSuit(i);
			int count = cards.size();
			if (cardCount <= 16) {
				if (count >= 4) {
					player.flip(i);
					return;
				}
			} else if (cardCount <= 20) {
				if (count >= 5) {
					player.flip(i);
					return;
				}
			} else if (cardCount <= 25) {
				if (count >= 6) {
					player.flip(i);
					return;
				}
			}
		}
		if (cardCount >= 22 && player.flipAbility(Card.SUIT_JOKER)) {
			LinkedList<Card> cards = player.getCardsInSuit(Card.SUIT_TRUMP);
			int count = 0;
			ListIterator<Card> itor = cards.listIterator();
			while (itor.hasNext()) {
				Card card = itor.next();
				if (card.isCerternTrump()) {
					count++;
				} else {
					break;
				}
			}
			if (cardCount <= 24) {
				if (count >= 4) {
					player.flip(Card.SUIT_JOKER);
				}
			} else if (cardCount == 25) {
				if (count >= 5) {
					player.flip(Card.SUIT_JOKER);
				}
			}
		}
	}

	@Override
	public boolean checkLegalBeforePlay(Player player,
			List<Card> cardsToBePlayed, PlayController pc) {
		// 检查牌数
		if (cardsToBePlayed.size() == 0) {
			return false;
		}

		ArrayList<LinkedList<Card>> playedCard = pc
				.getPlayedCardsInPlayingOrder();
		int order = playedCard.size();
		if (order == 0) {
			// 第一个出牌，需要所有牌都是主牌或同一种副牌
			int suit = cardsToBePlayed.get(0).suitDistinguishTrump();
			for (int i = 1; i < cardsToBePlayed.size(); i++) {
				if (cardsToBePlayed.get(i).suitDistinguishTrump() != suit) {
					return false;
				}
			}
		} else {
			LinkedList<Card> first = playedCard.get(0);
			int count = first.size();
			// 出牌数要跟首家相等
			if (cardsToBePlayed.size() != count) {
				return false;
			}
			// 如果没有同花色的牌，ok
			List<Card> ownedSameSuitCards = player.getCardsInSuit(first
					.getFirst().suitDistinguishTrump());
			int ownedSameSuitCount = ownedSameSuitCards.size();
			if (ownedSameSuitCount == 0) {
				return true;
			}
			// 统计要出的牌是否同花以及与首家相同花色的牌数
			boolean isSameSuit = true;
			int playSameSuitCount = 0;
			for (int i = 0; i < cardsToBePlayed.size(); i++) {
				if (cardsToBePlayed.get(i).suitDistinguishTrump() != first
						.get(0).suitDistinguishTrump()) {
					isSameSuit = false;
				} else {
					playSameSuitCount++;
				}
			}
			// 所有牌需与首家的牌同花色，如不同，则已有的牌数小于要出牌数且要出的牌数等于已有的牌数
			if (isSameSuit == false) {
				if (ownedSameSuitCount >= count
						|| playSameSuitCount != ownedSameSuitCount) {
					return false;
				}
			}
			// 如果花色都相同，则牌型要相同，否则判断无此牌型
			LinkedList<Card> recommond = playCard(player, pc);
			return new CardPattern(cardsToBePlayed).isSamePattern(new CardPattern(recommond));
		}
		return true;
	}

	@Override
	public void buryKitty(Player player) {
		// 判断有多少张主，有没有大王，可以垫多少分
		LinkedList<Card> cardToBeBuried = new LinkedList<Card>();
		int count = getKittyCount();
		int i = 0;
		while (count > 0 && i <= Card.SUIT_TRUMP) {
			List<Card> cards = player.getCardsInSuit(i);
			for (int j = cards.size() - 1; j >= 0; j--) {
				cardToBeBuried.add(cards.get(j));
				count--;
				if (count == 0) {
					break;
				}
			}
			i++;
		}
		player.doBuryCards(cardToBeBuried);
	}

	@Override
	public LinkedList<Card> playCard(Player player, PlayController pc) {
		LinkedList<Card> cardsToBePlayed = new LinkedList<Card>();
		ArrayList<LinkedList<Card>> playedCard = pc.getPlayedCardsInPlayingOrder();
		int order = pc.currentOrder();
		switch (order) {
		case 0: 
		{
			// 出副牌的最大牌
			for (int s = 0; s < Card.SUIT_COUNT_WITHOUT_JOKER; s++) {
				LinkedList<Card> cards = player.getCardsInSuit(s);
				CardPattern cardPattern = new CardPattern(cards);
				if (cardPattern.tractors().size() != 0) {
					if (cardPattern.tractors().getFirst().getFirst().getFirst().number() == Card.MAX_NUMBER_IN_VICE) {
						cardsToBePlayed.addAll(cardPattern.tractorCards(0));
						break;
					}
				}
				if (cardPattern.pairs().size() != 0) {
					if (cardPattern.pairs().getFirst().getFirst().number() == Card.MAX_NUMBER_IN_VICE) {
						cardsToBePlayed.addAll(cardPattern.pairs().getFirst());
						if (cardPattern.singles().size() != 0 
								&& cardPattern.singles().getFirst().number() == Card.MAX_NUMBER_IN_VICE - 1) {
							cardsToBePlayed.add(cardPattern.singles().getFirst());
							break;
						}
					}
				}
				if (cardPattern.singles().size() != 0) {
					if (cardPattern.singles().getFirst().number() == Card.MAX_NUMBER_IN_VICE) {
						cardsToBePlayed.add(cardPattern.singles().getFirst());
						break;
					}
				}	
			}
			// 对牌的甩牌检测
			if (cardsToBePlayed.size() != 0) {
				int suit = cardsToBePlayed.getFirst().suit();
				LinkedList<Card> cards = player.getCardsInSuit(suit);
				CardPattern pattern = new CardPattern(cards);
				pattern.remove(cardsToBePlayed);
				for (int i = 0; i < pattern.pairs().size(); i++) {
					LinkedList<Card> pair = pattern.pairs().get(i);
					boolean shouldThrow = true;
					for (int n = cardsToBePlayed.getLast().number() - 1; n > pair.getFirst().number(); n--) {
						Card card = Card.getCard(suit, n);
						if (cards.indexOf(card) == -1) {
							shouldThrow = false;
							break;
						}
					}
					if (shouldThrow) {
						cardsToBePlayed.addAll(pair);
					}
				}
				return cardsToBePlayed;
			}
			
			for (int s = 0; s <= Card.SUIT_TRUMP; s++) {
				List<Card> cards = player.getCardsInSuit(s);
				CardPattern cardPattern = new CardPattern(cards);
				if (cardPattern.tractors().size() != 0) {
					cardsToBePlayed.addAll(cardPattern.tractorCards(0));
					return cardsToBePlayed;
				}
			}
			for (int s = 0; s <= Card.SUIT_TRUMP; s++) {
				List<Card> cards = player.getCardsInSuit(s);
				CardPattern cardPattern = new CardPattern(cards);
				if (cardPattern.pairs().size() != 0) {
					cardsToBePlayed.addAll(cardPattern.pairs().getFirst());
					return cardsToBePlayed;
				}
			}
			for (int s = 0; s <= Card.SUIT_TRUMP; s++) {
				List<Card> cards = player.getCardsInSuit(s);
				CardPattern cardPattern = new CardPattern(cards);
				if (cardPattern.singles().size() != 0) {
					cardsToBePlayed.add(cardPattern.singles().getFirst());
					return cardsToBePlayed;
				}
			}
		}
			break;
		case 1:
		case 2:
		case 3: {
			LinkedList<Card> first = playedCard.get(0);
			int suit = first.getFirst().suitDistinguishTrump();
			int count = first.size();
			List<Card> handyCards = player.getCardsInSuit(suit);
			int diff = count - handyCards.size();
			// 如果手上的牌少于要出的牌，则全部都出，并补充差额
			if (diff >= 0) {
				cardsToBePlayed.addAll(handyCards);
				for (int i = 0; diff > 0 && i <= Card.SUIT_TRUMP; i++) {
					if (i == suit) {
						continue;
					}
					List<Card> cards = player.getCardsInSuit(i);
					for (int j = 0; diff > 0 && j < cards.size(); j++) {
						Card card = cards.get(j);
						cardsToBePlayed.add(card);
						diff--;
					}
				}
			} else {
				// 按牌型出
				CardPattern largest = pc.largestCardPattern();
				CardPattern my = new CardPattern(handyCards);
				// 1.先满足拖拉机
				for (int i = 0; i < largest.tractors().size(); i++) {
					List<Card> tractor = largest.tractorCards(i);
					int size = tractor.size();
					// 1.1用拖拉机满足
					while (size > 0 && my.tractors().size() > 0) {
						List<Card> myTractor = my.tractorCards(0);
						int mySize = myTractor.size();
						// 如果小于等于牌数，直接出
						if (mySize <= size) {
							cardsToBePlayed.addAll(myTractor);
							my.remove(myTractor);
							size -= mySize;
						} else {
							// 如果大于，向后搜索等于的，没有等于的就拆
							for (int j = 0; j < my.tractors().size(); j++) {
								if (my.tractorCards(j).size() == size) {
									cardsToBePlayed.addAll(my.tractorCards(j));
									size = 0;
									break;
								}
							}
							if (size != 0) {
								List<Card> toPlayed = myTractor
										.subList(0, size);
								cardsToBePlayed.addAll(toPlayed);
								my.remove(toPlayed);
								size = 0;
							}
						}
					}
					// 1.2用对牌满足
					while (size > 0 && my.pairs().size() > 0) {
						LinkedList<Card> pair = my.pairs().getFirst();
						cardsToBePlayed.addAll(pair);
						my.remove(pair);
						size -= 2;
					}
					// 1.3用单牌满足
					while (size > 0) {
						Card single = my.singles().getFirst();
						cardsToBePlayed.add(single);
						my.remove(single);
						size--;
					}
				} // for (int i = 0; i < largest.tractors().size(); i++)
				// 2.再满足对牌
				for (int i = 0; i < largest.pairs().size(); i++) {
					// 2.1先用对牌满足
					int size = 2;
					while (size > 0 && my.pairs().size() > 0) {
						LinkedList<Card> pair = my.pairs().getFirst();
						cardsToBePlayed.addAll(pair);
						my.remove(pair);
						size -= 2;
					}
					// 2.2用拖拉机满足
					while (size > 0 && my.tractors().size() > 0) {
						List<Card> myTractor = my.tractorCards(0);
						List<Card> pair = myTractor.subList(0, 2);
						cardsToBePlayed.addAll(pair);
						my.remove(pair);
						size -= 2;
					}
					// 2.3用单牌满足
					while (size > 0) {
						Card single = my.singles().getFirst();
						cardsToBePlayed.add(single);
						my.remove(single);
						size--;
					}
				}
				// 3.最后满足单牌
				for (int i = 0; i < largest.singles().size(); i++) {
					int size = 1;
					// 3.1用单牌满足
					while (size > 0 && my.singles().size() > 0) {
						Card single = my.singles().getFirst();
						cardsToBePlayed.add(single);
						my.remove(single);
						size--;
					}
					// 3.2用对牌满足
					while (size > 0 && my.pairs().size() > 0) {
						Card card = my.pairs().getFirst().getFirst();
						cardsToBePlayed.add(card);
						my.remove(card);
						size = 0;
					}
					// 3.3用拖拉机满足
					while (size > 0 && my.tractors().size() > 0) {
						Card card = my.tractors().getFirst().getFirst()
								.getFirst();
						cardsToBePlayed.add(card);
						my.remove(card);
						size = 0;
					}
				}
			}
		}
			break;
		default:
			break;
		}
		return cardsToBePlayed;
	}

}
